﻿using Serilog;
using System;
using System.IO;

namespace CsharpTool.SerilogCore
{
    public static class SerilogLogConfig
    {
        /// <summary>
        /// 配置Serilog
        /// </summary>
        /// <param name="fileSizeLimitBytes">日志文件大小，默认10M</param>
        /// <param name="retainedFileCountLimit">日志文件保留份数，默认没有限制</param>
        /// <param name="loggerConfigure">全局写日志配置，不在异步写日志线程中执行</param>
        /// <param name="asyncLoggerConfigure">异步写日志配置</param>
        /// <param name="outputTemplate">日志记录模板</param>
        public static void ConfigSerilogLog(int fileSizeLimitBytes = 10 * 1024 * 1024, int? retainedFileCountLimit = null,
            string outputTemplate = "{Timestamp:HH:mm:ss.fff zzz} {Message:lj}{NewLine}{Exception}",
            string noDateOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
            string normalOutputTemplate = "{Timestamp:HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}", Action<LoggerConfiguration> loggerConfigure = null, Action<LoggerConfiguration> asyncLoggerConfigure = null, Action<LoggerConfiguration> asyncLoggerConfigure1 = null)
        {
            var loggerConfig = new LoggerConfiguration()
                    .MinimumLevel.Information()
                    .WriteTo.Logger(rlc => rlc.Filter.ByIncludingOnly(e => e.Properties.ContainsKey("Category") && !e.Properties.ContainsKey("Category1")).WriteTo.Async(a => {
                        var asyncLoggerConfig = a.Logger(lc => lc
                                .WriteTo.Map(
                                    le =>
                                    {
                                        return Path.Combine("logs", le.Timestamp.ToString("yyyyMMdd"), le.Properties["Category"].ToString().Trim('"'), le.Level.ToString(), "log.log");
                                    },
                                    (key, log) => log.File(key, rollingInterval: RollingInterval.Day,
                                        outputTemplate: outputTemplate, fileSizeLimitBytes: fileSizeLimitBytes, retainedFileCountLimit: retainedFileCountLimit, rollOnFileSizeLimit: true),
                                    sinkMapCountLimit: 1));

                        if (asyncLoggerConfigure != null)
                        {
                            asyncLoggerConfigure(asyncLoggerConfig);
                        }
                    }
                        , bufferSize: int.MaxValue))

                    .WriteTo.Logger(rlc => rlc.Filter.ByIncludingOnly(e => e.Properties.ContainsKey("Category") && e.Properties.ContainsKey("Category1")).WriteTo.Async(a => {
                        var asyncLoggerConfig = a.Logger(lc => lc
                                .WriteTo.Map(
                                    le =>
                                    {
                                        return Path.Combine("logs", le.Timestamp.ToString("yyyyMMdd"), le.Properties["Category"].ToString().Trim('"'), le.Properties["Category1"].ToString().Trim('"'), le.Level.ToString(), "log.log");
                                    },
                                    (key, log) => log.File(key, rollingInterval: RollingInterval.Day,
                                        outputTemplate: outputTemplate, fileSizeLimitBytes: fileSizeLimitBytes, retainedFileCountLimit: retainedFileCountLimit, rollOnFileSizeLimit: true),
                                    sinkMapCountLimit: 1));

                        if (asyncLoggerConfigure1 != null)
                        {
                            asyncLoggerConfigure1(asyncLoggerConfig);
                        }
                    }
                        , bufferSize: int.MaxValue))

                    .WriteTo.Logger(rlc => rlc.Filter.ByIncludingOnly(e => true).WriteTo.Async(a => {
                        a.Logger(lc => lc
                                .WriteTo.Map(
                                    le =>
                                    {
                                        return Path.Combine("logs", le.Timestamp.ToString("yyyyMMdd"), "Default", le.Level.ToString(), "log.log");
                                    },
                                    (key, log) => log.File(key, rollingInterval: RollingInterval.Day,
                                        outputTemplate: normalOutputTemplate, fileSizeLimitBytes: fileSizeLimitBytes, retainedFileCountLimit: retainedFileCountLimit, rollOnFileSizeLimit: true),
                                    sinkMapCountLimit: 1));
                    }
                        , bufferSize: int.MaxValue));
            if (loggerConfigure != null)
            {
                loggerConfigure(loggerConfig);
            }

            Log.Logger = loggerConfig.CreateLogger();
        }
    }
}
